package persistencia.facturas;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import modelo.Factura;
import modelo.enums.Tarifa;
import modelo.utils.ListaFacturas;

public class BDFacturaImpl implements BDFactura
{
    private static final int CANTIDAD = 10;
    public final static Factura FACTURA_NULL = new Factura();

    private EntityManagerFactory emf;
    private EntityManager em;
    private EntityTransaction tx;

    public BDFacturaImpl()
    {
        super();
        emf = Persistence.createEntityManagerFactory("test");
        em = emf.createEntityManager();
        tx = em.getTransaction();
        initDB();
    }

    private void initDB()
    {
        for (int i = 0; i < CANTIDAD; i++)
        {
            insert(new Factura(i, i + 5, Tarifa.NORMAL, new Date(), Integer.toString(i),
                    Integer.toString(i % 3)));
        }
    }

    @Override
    public ListaFacturas getAll()
    {
        Query query = em.createNamedQuery(Factura.RECUPERA_TODAS);
        return new ListaFacturas(query.getResultList());
    }

    @Override
    public ListaFacturas getByMetros(int desde, int hasta)
    {
        Query query = em.createNamedQuery(Factura.RECUPERA_TODAS_POR_METROS)
                .setParameter("metrosDesde", desde).setParameter("metrosHasta", hasta);
        return new ListaFacturas(query.getResultList());
    }

    @Override
    public ListaFacturas getByMetrosYNIF(int desde, int hasta, String nif)
    {
        Query query = em.createNamedQuery(Factura.RECUPERA_TODAS_POR_METROS_Y_NIF)
                .setParameter("metrosDesde", desde).setParameter("metrosHasta", hasta)
                .setParameter("nif", nif);
        return new ListaFacturas(query.getResultList());
    }

    @Override
    public ListaFacturas findByNif(String nif)
    {
        Query query = em.createNamedQuery(Factura.RECUPERA_TODAS_POR_NIF).setParameter("nif", nif);
        return new ListaFacturas(query.getResultList());
    }

    @Override
    public Factura findByNifAndCode(String nif, int code)
    {
        Query query = em.createNamedQuery(Factura.RECUPERA_TODAS_POR_NIF_Y_CODIGO)
                .setParameter("nif", nif).setParameter("codigo", code);
        List<Factura> result = query.getResultList();

        if (result.isEmpty())
            return FACTURA_NULL;
        return result.get(0);
    }

    @Override
    public Factura findByCode(int codigo)
    {
        Query query = em.createNamedQuery(Factura.RECUPERA_TODAS_POR_CODIGO).setParameter("codigo",
                codigo);
        List<Factura> resultado = query.getResultList();
        if (resultado.isEmpty())
            return FACTURA_NULL;
        return resultado.get(0);
    }

    @Override
    public boolean update(Factura factura)
    {
        tx.begin();

        Factura enLista = findByCode(factura.getCodigo());
        if (enLista != FACTURA_NULL)
        {
            enLista.actualiza(factura);
        }

        tx.commit();
        return true;
    }

    @Override
    public boolean delete(int codigo)
    {
        tx.begin();

        Factura f = findByCode(codigo);
        em.remove(f);

        tx.commit();

        return true;
    }

    @Override
    public boolean delete(String nif)
    {
        Query query = em.createNamedQuery(Factura.RECUPERA_TODAS_POR_NIF).setParameter("nif", nif);
        List<Factura> resultado = query.getResultList();

        tx.begin();
        em.remove(resultado);
        tx.commit();

        return true;
    }

    @Override
    public void insert(Factura factura)
    {
        tx.begin();

        em.persist(factura);

        tx.commit();
    }

}
